return FALSE;
}
-/* _gdk_synthesize_crossing_events only works inside one toplevel.
- This function splits things into two calls if needed, converting the
- coordinates to the right toplevel */
-static void
-synthesize_crossing_events (GdkDisplay *display,
- GdkDevice *device,
- GdkDevice *source_device,
- GdkWindow *src_window,
- GdkWindow *dest_window,
- GdkCrossingMode crossing_mode,
- guint32 time,
- gulong serial)
-{
- GdkWindow *src_toplevel, *dest_toplevel;
- GdkModifierType state;
- double x, y;
-
- if (src_window)
- src_toplevel = gdk_window_get_toplevel (src_window);
- else
- src_toplevel = NULL;
- if (dest_window)
- dest_toplevel = gdk_window_get_toplevel (dest_window);
- else
- dest_toplevel = NULL;
-
- if (src_toplevel == NULL && dest_toplevel == NULL)
- return;
-
- if (src_toplevel == NULL ||
- src_toplevel == dest_toplevel)
- {
- /* Same toplevels */
- gdk_window_get_device_position_double (dest_toplevel,
- device,
- &x, &y, &state);
- _gdk_synthesize_crossing_events (display,
- src_window,
- dest_window,
- device, source_device,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial, FALSE);
- }
- else if (dest_toplevel == NULL)
- {
- gdk_window_get_device_position_double (src_toplevel,
- device,
- &x, &y, &state);
- _gdk_synthesize_crossing_events (display,
- src_window,
- NULL,
- device, source_device,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial, FALSE);
- }
- else
- {
- /* Different toplevels */
- gdk_window_get_device_position_double (src_toplevel,
- device,
- &x, &y, &state);
- _gdk_synthesize_crossing_events (display,
- src_window,
- NULL,
- device, source_device,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial, FALSE);
- gdk_window_get_device_position_double (dest_toplevel,
- device,
- &x, &y, &state);
- _gdk_synthesize_crossing_events (display,
- NULL,
- dest_window,
- device, source_device,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial, FALSE);
- }
-}
-
static GdkWindow *
get_current_toplevel (GdkDisplay *display,
GdkDevice *device,
guint32 time,
gulong serial)
{
- GdkWindow *src_window, *pointer_window, *new_toplevel;
+ GdkWindow *pointer_window, *new_toplevel;
GdkPointerWindowInfo *info;
GList *old_grabs;
GdkModifierType state;
if (grab)
{
/* New grab is in effect */
-
- /* We need to generate crossing events for the grab.
- * However, there are never any crossing events for implicit grabs
- * TODO: ... Actually, this could happen if the pointer window
- * doesn't have button mask so a parent gets the event...
- */
if (!grab->implicit)
{
- /* We send GRAB crossing events from the window under the pointer to the
- grab window. Except if there is an old grab then we start from that */
- if (last_grab)
- src_window = last_grab->window;
- else
- src_window = info->window_under_pointer;
-
- if (src_window != grab->window)
- synthesize_crossing_events (display, device, source_device,
- src_window, grab->window,
- GDK_CROSSING_GRAB, time, serial);
-
/* !owner_event Grabbing a window that we're not inside, current status is
now NULL (i.e. outside grabbed window) */
if (!grab->owner_events && info->window_under_pointer != grab->window)
NULL, NULL);
}
- if (!info->need_touch_press_enter &&
- pointer_window != last_grab->window)
- synthesize_crossing_events (display, device, source_device,
- last_grab->window, pointer_window,
- GDK_CROSSING_UNGRAB, time, serial);
-
/* We're now ungrabbed, update the window_under_pointer */
_gdk_display_set_window_under_pointer (display, device, pointer_window);
}
return FALSE;
}
-static void
-convert_toplevel_coords_to_window (GdkWindow *window,
- gdouble toplevel_x,
- gdouble toplevel_y,
- gdouble *window_x,
- gdouble *window_y)
-{
- GdkWindow *parent;
- gdouble x, y;
- GList *children, *l;
-
- x = toplevel_x;
- y = toplevel_y;
-
- children = NULL;
- while ((parent = window->parent) != NULL &&
- (parent->window_type != GDK_WINDOW_ROOT))
- {
- children = g_list_prepend (children, window);
- window = parent;
- }
-
- for (l = children; l != NULL; l = l->next)
- gdk_window_coords_from_parent (l->data, x, y, &x, &y);
-
- g_list_free (children);
-
- *window_x = x;
- *window_y = y;
-}
-
GdkWindow *
_gdk_window_find_child_at (GdkWindow *window,
double x,
/* send motion events if the right buttons are down */
-static GdkWindow *
-find_common_ancestor (GdkWindow *win1,
- GdkWindow *win2)
-{
- GdkWindow *tmp;
- GList *path1 = NULL, *path2 = NULL;
- GList *list1, *list2;
-
- tmp = win1;
- while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
- {
- path1 = g_list_prepend (path1, tmp);
- tmp = tmp->parent;
- }
-
- tmp = win2;
- while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
- {
- path2 = g_list_prepend (path2, tmp);
- tmp = tmp->parent;
- }
-
- list1 = path1;
- list2 = path2;
- tmp = NULL;
- while (list1 && list2 && (list1->data == list2->data))
- {
- tmp = list1->data;
- list1 = list1->next;
- list2 = list2->next;
- }
- g_list_free (path1);
- g_list_free (path2);
-
- return tmp;
-}
-
GdkEvent *
_gdk_make_event (GdkWindow *window,
GdkEventType type,
return event;
}
-static void
-send_crossing_event (GdkDisplay *display,
- GdkWindow *toplevel,
- GdkWindow *window,
- GdkEventType type,
- GdkCrossingMode mode,
- GdkNotifyType notify_type,
- GdkWindow *subwindow,
- GdkDevice *device,
- GdkDevice *source_device,
- gdouble toplevel_x,
- gdouble toplevel_y,
- GdkModifierType mask,
- guint32 time_,
- GdkEvent *event_in_queue,
- gulong serial)
-{
- GdkEvent *event;
- guint32 window_event_mask, type_event_mask;
- GdkDeviceGrabInfo *grab;
- GdkTouchGrabInfo *touch_grab = NULL;
- GdkPointerWindowInfo *pointer_info;
- gboolean block_event = FALSE;
- GdkEventSequence *sequence;
-
- grab = _gdk_display_has_device_grab (display, device, serial);
- pointer_info = _gdk_display_get_pointer_info (display, device);
-
- sequence = gdk_event_get_event_sequence (event_in_queue);
- if (sequence)
- touch_grab = _gdk_display_has_touch_grab (display, device, sequence, serial);
-
- if (touch_grab)
- {
- if (window != touch_grab->window)
- return;
-
- window_event_mask = touch_grab->event_mask;
- }
- else if (grab != NULL &&
- !grab->owner_events)
- {
- /* !owner_event => only report events wrt grab window, ignore rest */
- if ((GdkWindow *)window != grab->window)
- return;
- window_event_mask = grab->event_mask;
- }
- else
- window_event_mask = window->event_mask;
-
- if (type == GDK_ENTER_NOTIFY &&
- (pointer_info->need_touch_press_enter ||
- (source_device &&
- gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)) &&
- mode != GDK_CROSSING_TOUCH_BEGIN &&
- mode != GDK_CROSSING_TOUCH_END)
- {
- pointer_info->need_touch_press_enter = TRUE;
- block_event = TRUE;
- }
- else if (type == GDK_LEAVE_NOTIFY)
- {
- type_event_mask = GDK_LEAVE_NOTIFY_MASK;
- window->devices_inside = g_list_remove (window->devices_inside, device);
-
- if (!window->support_multidevice && window->devices_inside)
- {
- /* Block leave events unless it's the last pointer */
- block_event = TRUE;
- }
- }
- else
- {
- type_event_mask = GDK_ENTER_NOTIFY_MASK;
-
- if (!window->support_multidevice && window->devices_inside)
- {
- /* Only emit enter events for the first device */
- block_event = TRUE;
- }
-
- if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER &&
- gdk_device_get_mode (device) != GDK_MODE_DISABLED &&
- !g_list_find (window->devices_inside, device))
- window->devices_inside = g_list_prepend (window->devices_inside, device);
- }
-
- if (block_event)
- return;
-
- if (window_event_mask & type_event_mask)
- {
- event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
- gdk_event_set_device (event, device);
- gdk_event_set_seat (event, gdk_device_get_seat (device));
-
- if (source_device)
- gdk_event_set_source_device (event, source_device);
-
- event->crossing.time = time_;
- event->crossing.subwindow = subwindow;
- if (subwindow)
- g_object_ref (subwindow);
- convert_toplevel_coords_to_window ((GdkWindow *)window,
- toplevel_x, toplevel_y,
- &event->crossing.x, &event->crossing.y);
- event->crossing.x_root = toplevel_x + toplevel->x;
- event->crossing.y_root = toplevel_y + toplevel->y;
- event->crossing.mode = mode;
- event->crossing.detail = notify_type;
- event->crossing.focus = FALSE;
- event->crossing.state = mask;
- }
-}
-
-
-/* The coordinates are in the toplevel window that src/dest are in.
- * src and dest are always (if != NULL) in the same toplevel, as
- * we get a leave-notify and set the window_under_pointer to null
- * before crossing to another toplevel.
- */
-void
-_gdk_synthesize_crossing_events (GdkDisplay *display,
- GdkWindow *src,
- GdkWindow *dest,
- GdkDevice *device,
- GdkDevice *source_device,
- GdkCrossingMode mode,
- double toplevel_x,
- double toplevel_y,
- GdkModifierType mask,
- guint32 time_,
- GdkEvent *event_in_queue,
- gulong serial,
- gboolean non_linear)
-{
- GdkWindow *c;
- GdkWindow *win, *last, *next;
- GList *path, *list;
- GdkWindow *a;
- GdkWindow *b;
- GdkWindow *toplevel;
- GdkNotifyType notify_type;
-
- /* TODO: Don't send events to toplevel, as we get those from the windowing system */
-
- a = (src && GDK_IS_WINDOW (src)) ? src : NULL;
- b = (dest && GDK_IS_WINDOW (dest)) ? dest : NULL;
-
- if (src == dest)
- return; /* No crossings generated between src and dest */
-
- if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
- {
- if (a && gdk_window_get_device_events (src, device) == 0)
- a = NULL;
-
- if (b && gdk_window_get_device_events (dest, device) == 0)
- b = NULL;
- }
-
- if (!a && !b)
- return;
-
- c = find_common_ancestor (a, b);
-
- non_linear |= (c != a) && (c != b);
-
- if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
- {
- toplevel = gdk_window_get_toplevel (a);
-
- /* Traverse up from a to (excluding) c sending leave events */
- if (non_linear)
- notify_type = GDK_NOTIFY_NONLINEAR;
- else if (c == a)
- notify_type = GDK_NOTIFY_INFERIOR;
- else
- notify_type = GDK_NOTIFY_ANCESTOR;
- send_crossing_event (display, toplevel,
- a, GDK_LEAVE_NOTIFY,
- mode,
- notify_type,
- NULL, device, source_device,
- toplevel_x, toplevel_y,
- mask, time_,
- event_in_queue,
- serial);
-
- if (c != a)
- {
- if (non_linear)
- notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
- else
- notify_type = GDK_NOTIFY_VIRTUAL;
-
- last = a;
- win = a->parent;
- while (win != c && win->window_type != GDK_WINDOW_ROOT)
- {
- send_crossing_event (display, toplevel,
- win, GDK_LEAVE_NOTIFY,
- mode,
- notify_type,
- (GdkWindow *)last,
- device, source_device,
- toplevel_x, toplevel_y,
- mask, time_,
- event_in_queue,
- serial);
-
- last = win;
- win = win->parent;
- }
- }
- }
-
- if (b) /* Might not be a dest, e.g. if we're moving out of the window */
- {
- toplevel = gdk_window_get_toplevel ((GdkWindow *)b);
-
- /* Traverse down from c to b */
- if (c != b)
- {
- path = NULL;
- win = b->parent;
- while (win != c && win->window_type != GDK_WINDOW_ROOT)
- {
- path = g_list_prepend (path, win);
- win = win->parent;
- }
-
- if (non_linear)
- notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
- else
- notify_type = GDK_NOTIFY_VIRTUAL;
-
- list = path;
- while (list)
- {
- win = list->data;
- list = list->next;
- if (list)
- next = list->data;
- else
- next = b;
-
- send_crossing_event (display, toplevel,
- win, GDK_ENTER_NOTIFY,
- mode,
- notify_type,
- (GdkWindow *)next,
- device, source_device,
- toplevel_x, toplevel_y,
- mask, time_,
- event_in_queue,
- serial);
- }
- g_list_free (path);
- }
-
-
- if (non_linear)
- notify_type = GDK_NOTIFY_NONLINEAR;
- else if (c == a)
- notify_type = GDK_NOTIFY_ANCESTOR;
- else
- notify_type = GDK_NOTIFY_INFERIOR;
-
- send_crossing_event (display, toplevel,
- b, GDK_ENTER_NOTIFY,
- mode,
- notify_type,
- NULL,
- device, source_device,
- toplevel_x, toplevel_y,
- mask, time_,
- event_in_queue,
- serial);
- }
-}
-
void
_gdk_display_set_window_under_pointer (GdkDisplay *display,
GdkDevice *device,